package com.pig4cloud.pig.iotData.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.log.annotation.SysLog;
import com.pig4cloud.pig.common.security.annotation.Inner;
import com.pig4cloud.pig.iotData.entity.IotDataKgbotcamFileEntity;
import com.pig4cloud.pig.iotData.service.IotDataKgbotcamFileService;
import com.pig4cloud.pig.iotData.vo.IotDataKgBotCamDetecedFileFormParamVo;
import com.pig4cloud.pig.iotData.vo.IotDataKgBotCamFileFormParamVo;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 多肉kgbotcam采集的图片文件管理表
 *
 * @author lty
 * @date 2024-11-07 22:24:12
 */
@RestController
@RequiredArgsConstructor
//@PreAuthorize("@pms.hasPermission('iot_iotDevice_view')" ) todo 对于任何的设备数据查看 只要由iotdevice设备查看权限就好，不用单分权限 先不加
@RequestMapping("/duorouKgbotcamFile" )
@Tag(description = "duorouKgbotcamFile" , name = "多肉kgbotcam采集的图片文件管理表管理" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class IotDataKgbotcamFileController {

    private final IotDataKgbotcamFileService iotDataKgbotcamFileService;


	/**
	 * 获取统计分析 最近一周的统计
	 */
	@Operation(summary = "统计数据_周" , description = "统计数据_周" )
	@GetMapping("/getDataAnalysisByWeek")
	public R getDataAnalysisByWeek(@ParameterObject IotDataKgbotcamFileEntity duorouKgbotcamFile) {
		//		.eq("predict_status","不健康")
		System.out.println(duorouKgbotcamFile);
		QueryWrapper<IotDataKgbotcamFileEntity> queryWrapper = new QueryWrapper<>();

		queryWrapper.select("DATE(create_time) as xdata", "COUNT(*) as ydata")
				.eq(duorouKgbotcamFile.getPredictStatus() != null, "predict_status", duorouKgbotcamFile.getPredictStatus())
				.eq(duorouKgbotcamFile.getIotDeviceId() != null, "iot_device_id", duorouKgbotcamFile.getIotDeviceId())
				.apply("create_time >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)")
				.groupBy("DATE(create_time)")
				.orderByDesc("xdata");

		// 使用 listMaps() 返回多条记录，一条记录为xdata ydata是值
		List<Map<String, Object>> resultList = iotDataKgbotcamFileService.listMaps(queryWrapper);
		//		处理数据 对于数据库中那天没有的日期 把y值补0
		List<Map<String, Object>> handleResultList = handleWeekAnalysisData(resultList);
		return R.ok(handleResultList);
	}
	/**
	 * 处理 返回的一周的数据 对数据处理得到最终结果
	 */
	public List<Map<String, Object>> handleWeekAnalysisData(List<Map<String, Object>> resultList) {
		// 获取当前日期
		LocalDate today = LocalDate.now();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

		// 创建过去 7 天的日期列表
		Map<String, Integer> dateMap = new LinkedHashMap<>();
		for (int i = 6; i >= 0; i--) {
			String date = today.minusDays(i).format(formatter);
			dateMap.put(date, 0);
		}

		// 将查询结果转换为 Map 以便快速查找
		Map<String, Integer> queryDataMap = resultList.stream()
				.collect(Collectors.toMap(
						data -> data.get("xdata").toString(),
						data -> Integer.parseInt(data.get("ydata").toString())
				));

		// 合并数据
		dateMap.forEach((date, count) -> {
			if (queryDataMap.containsKey(date)) {
				dateMap.put(date, queryDataMap.get(date));
			}
		});

		// 转换为 List<Map<String, Object>> 格式
		List<Map<String, Object>> completeList = dateMap.entrySet().stream()
				.map(entry -> {
					Map<String, Object> map = new HashMap<>();
					map.put("xdata", entry.getKey());
					map.put("ydata", entry.getValue());
					return map;
				})
				.collect(Collectors.toList());

		return completeList;
	}



	/**
	 * 获取统计分析 最近12个月的统计
	 */
	@Operation(summary = "统计数据_月" , description = "统计数据_月" )
	@GetMapping("/getDataAnalysisByMonth")
	public R getDataAnalysisByMonth(@ParameterObject IotDataKgbotcamFileEntity duorouKgbotcamFile) {
		QueryWrapper<IotDataKgbotcamFileEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper
				.select("DATE_FORMAT(create_time, '%Y-%m') as xdata", "COUNT(*) as ydata")
				.eq(duorouKgbotcamFile.getPredictStatus() != null, "predict_status", duorouKgbotcamFile.getPredictStatus())
				.eq(duorouKgbotcamFile.getIotDeviceId() != null, "iot_device_id", duorouKgbotcamFile.getIotDeviceId())
				.apply("create_time >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)")
				.groupBy("DATE_FORMAT(create_time, '%Y-%m')")
				.orderByAsc("xdata");

// 使用 listMaps() 返回多条记录
		List<Map<String, Object>> resultList = iotDataKgbotcamFileService.listMaps(queryWrapper);

// 调用方法补全缺失月份数据
		List<Map<String, Object>> handleResultList = handleMonthlyAnalysisData(resultList);
		return R.ok(handleResultList);
	}
	/**
	 * 处理月份返回的数据
	 * @param resultList
	 * @return
	 */
	public List<Map<String, Object>> handleMonthlyAnalysisData(List<Map<String, Object>> resultList) {
		// 获取当前日期
		LocalDate currentDate = LocalDate.now();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");

		// 创建最近 12 个月的日期列表
		Map<String, Integer> dateMap = new LinkedHashMap<>();
		for (int i = 11; i >= 0; i--) {
			String month = currentDate.minusMonths(i).format(formatter);
			dateMap.put(month, 0);
		}

		// 将查询结果转换为 Map 以便快速查找
		Map<String, Integer> queryDataMap = resultList.stream()
				.collect(Collectors.toMap(
						data -> data.get("xdata").toString(),
						data -> Integer.parseInt(data.get("ydata").toString())
				));

		// 合并数据库查询结果到日期列表
		dateMap.forEach((month, count) -> {
			if (queryDataMap.containsKey(month)) {
				dateMap.put(month, queryDataMap.get(month));
			}
		});

		// 转换为 List<Map<String, Object>> 格式
		List<Map<String, Object>> completeList = dateMap.entrySet().stream()
				.map(entry -> {
					Map<String, Object> map = new HashMap<>();
					map.put("xdata", entry.getKey());
					map.put("ydata", entry.getValue());
					return map;
				})
				.collect(Collectors.toList());

		return completeList;
	}




	@Operation(summary = "统计数据_年" , description = "统计数据_年" )
	@GetMapping("/getDataAnalysisByYear")
	public R getDataAnalysisByYear(@ParameterObject IotDataKgbotcamFileEntity duorouKgbotcamFile) {
		QueryWrapper<IotDataKgbotcamFileEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper
				.select("YEAR(create_time) as xdata", "COUNT(*) as ydata")
				.eq(duorouKgbotcamFile.getPredictStatus() != null, "predict_status", duorouKgbotcamFile.getPredictStatus())
				.eq(duorouKgbotcamFile.getIotDeviceId() != null, "iot_device_id", duorouKgbotcamFile.getIotDeviceId())
				.apply("create_time >= DATE_SUB(CURDATE(), INTERVAL 7 YEAR)")
				.groupBy("YEAR(create_time)")
				.orderByAsc("xdata");

// 使用 listMaps() 返回多条记录
		List<Map<String, Object>> resultList = iotDataKgbotcamFileService.listMaps(queryWrapper);

// 调用方法补全缺失年份数据
		List<Map<String, Object>> handleResultList = handleYearlyAnalysisData(resultList);
		return R.ok(handleResultList);
	}

	/***
	 * 处理年份的data analysis数据
	 * @param resultList
	 * @return
	 */
	public List<Map<String, Object>> handleYearlyAnalysisData(List<Map<String, Object>> resultList) {
		// 获取当前年份
		int currentYear = LocalDate.now().getYear();

		// 创建最近 7 年的年份列表
		Map<String, Integer> yearMap = new LinkedHashMap<>();
		for (int i = 6; i >= 0; i--) {
			String year = String.valueOf(currentYear - i);
			yearMap.put(year, 0);
		}

		// 将查询结果转换为 Map 以便快速查找
		Map<String, Integer> queryDataMap = resultList.stream()
				.collect(Collectors.toMap(
						data -> data.get("xdata").toString(),
						data -> Integer.parseInt(data.get("ydata").toString())
				));

		// 合并数据库查询结果到年份列表
		yearMap.forEach((year, count) -> {
			if (queryDataMap.containsKey(year)) {
				yearMap.put(year, queryDataMap.get(year));
			}
		});

		// 转换为 List<Map<String, Object>> 格式
		List<Map<String, Object>> completeList = yearMap.entrySet().stream()
				.map(entry -> {
					Map<String, Object> map = new HashMap<>();
					map.put("xdata", entry.getKey());
					map.put("ydata", entry.getValue());
					return map;
				})
				.collect(Collectors.toList());

		return completeList;
	}





	/**
     * 分页查询
     * @param page 分页对象
     * @param duorouKgbotcamFile 多肉kgbotcam采集的图片文件管理表
     * @return
     */
    @Operation(summary = "分页查询" , description = "分页查询" )
    @GetMapping("/page" )
    public R getDuorouKgbotcamFilePage(@ParameterObject Page page, @ParameterObject IotDataKgbotcamFileEntity duorouKgbotcamFile) {
        LambdaQueryWrapper<IotDataKgbotcamFileEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(StrUtil.isNotBlank(duorouKgbotcamFile.getPredictStatus()), IotDataKgbotcamFileEntity::getPredictStatus,duorouKgbotcamFile.getPredictStatus());
		wrapper.eq(Objects.nonNull(duorouKgbotcamFile.getIotDeviceId()), IotDataKgbotcamFileEntity::getIotDeviceId,duorouKgbotcamFile.getIotDeviceId());
//		查询出大于这个时间段的
		wrapper.ge(Objects.nonNull(duorouKgbotcamFile.getCreateTime()), IotDataKgbotcamFileEntity::getCreateTime,duorouKgbotcamFile.getCreateTime());
		wrapper.orderByDesc(IotDataKgbotcamFileEntity::getCreateTime);
		return R.ok(iotDataKgbotcamFileService.page(page, wrapper));
    }


    /**
     * 通过id查询多肉kgbotcam采集的图片文件管理表
     * @param id id
     * @return R
     */
    @Operation(summary = "通过id查询" , description = "通过id查询" )
    @GetMapping("/{id}" )
    public R getById(@PathVariable("id" ) Long id) {
        return R.ok(iotDataKgbotcamFileService.getById(id));
    }


	/**
	 * 导出excel 表格
	 * @param duorouKgbotcamFile 查询条件
	 * @param ids 导出指定ID
	 * @return excel 文件流
	 */
	@ResponseExcel
	@GetMapping("/export")
	public List<IotDataKgbotcamFileEntity> export(IotDataKgbotcamFileEntity duorouKgbotcamFile, Long[] ids) {
		return iotDataKgbotcamFileService.list(Wrappers.lambdaQuery(duorouKgbotcamFile).in(ArrayUtil.isNotEmpty(ids), IotDataKgbotcamFileEntity::getId, ids));
	}


    /**
     * 修改多肉kgbotcam采集的图片文件管理表
     * @param duorouKgbotcamFile 多肉kgbotcam采集的图片文件管理表
     * @return R
     */
    @Operation(summary = "修改多肉kgbotcam采集的图片文件管理表" , description = "修改多肉kgbotcam采集的图片文件管理表" )
    @SysLog("修改多肉kgbotcam采集的图片文件管理表" )
    @PutMapping
    public R updateById(@RequestBody IotDataKgbotcamFileEntity duorouKgbotcamFile) {
        return R.ok(iotDataKgbotcamFileService.updateById(duorouKgbotcamFile));
    }



	/**
	 * 通过id删除多肉kgbotcam采集的图片文件管理表
	 * @param ids id列表
	 * @return R
	 */
	@Operation(summary = "通过id删除多肉kgbotcam采集的图片文件管理表" , description = "通过id删除多肉kgbotcam采集的图片文件管理表" )
	@SysLog("通过id删除多肉kgbotcam采集的图片文件管理表" )
	@DeleteMapping
	public R removeById(@RequestBody Long[] ids) {
		for (Long id : ids) {
			iotDataKgbotcamFileService.deleteFile(id);
		}
		return R.ok();
	}



	/**
	 * 上传文件进行多肉图片检测 文件名采用uuid,避免原始文件名中带"-"符号导致下载的时候解析出现异常
	 * @param file 资源
	 * @return R(/ admin / bucketName / filename)
	 */
	@PostMapping(value = "/upload/toDet")
	public R uploadToDetectFile(@RequestPart("file") MultipartFile file) {
		IotDataKgbotcamFileEntity iotDataKgbotcamFileEntity = new IotDataKgbotcamFileEntity();
		iotDataKgbotcamFileEntity.setIotDeviceId(1853629857521487873L); //todo 对于这个接口 作为测试 设置为默认的IO台设备

		R<Object> rmap = iotDataKgbotcamFileService.uploadToDetectFile(file, iotDataKgbotcamFileEntity);
		if(rmap.getCode()!= CommonConstants.SUCCESS){
			return rmap;
		}
		Map<String, Object> data = (Map<String, Object>)rmap.getData();
		IotDataKgbotcamFileEntity re = (IotDataKgbotcamFileEntity)data.get("re");
		iotDataKgbotcamFileService.detDuoRouFileExecutor(re);//todo 1 异步监测照片文件是否有病虫  如果有的话直接插入消息表里面 并发邮件通知
		//todo 2 异步监测照片文件的繁育状况  如果有情况的话直接插入消息表里面 并发邮件通知
		return rmap;
	}

	/**
	 * 上传文件进行多肉图片检测（同时携带其他参数） 文件名采用uuid,避免原始文件名中带"-"符号导致下载的时候解析出现异常
	 * @param fileFormParam 资源
	 * @return R(/ admin / bucketName / filename)
	 */
	@PostMapping(value = "/upload/toDetMore")
	public R uploadToDetectFileMore(@ModelAttribute IotDataKgBotCamFileFormParamVo fileFormParam) {
		MultipartFile file = fileFormParam.getFile();
		IotDataKgbotcamFileEntity duorouKgbotcamFile = new IotDataKgbotcamFileEntity();
		duorouKgbotcamFile.setIotDeviceId(fileFormParam.getIotDeviceId());

		R<Object> rmap = iotDataKgbotcamFileService.uploadToDetectFile(file,duorouKgbotcamFile);
		if(rmap.getCode()!= CommonConstants.SUCCESS){
			return rmap;
		}
		Map<String, Object> data = (Map<String, Object>)rmap.getData();
		IotDataKgbotcamFileEntity re = (IotDataKgbotcamFileEntity)data.get("re");
		iotDataKgbotcamFileService.detDuoRouFileExecutor(re);
		return rmap;
	}




	/**
	 * 上传 已经检测后的多肉图片 更新原数据
	 * @param file 资源
	 * @return R(/ admin / bucketName / filename)
	 */
	@Deprecated
	@PostMapping(value = "/upload/detected/{fileId}")
	public R uploadDetectedFile(@RequestPart("file") MultipartFile file,@PathVariable Long fileId) {
		return iotDataKgbotcamFileService.uploadDetectedFile(file,fileId);
	}

	/**
	 * 上传 已经检测后的多肉图片 更新原数据
	 * @param
	 * @return R(/ admin / bucketName / filename)
	 */
	@Deprecated
	@PostMapping(value = "/upload/detected/more")
	public R uploadDetectedFileMore(@ModelAttribute IotDataKgBotCamDetecedFileFormParamVo duorouDetecedFileFormParam) {
		IotDataKgbotcamFileEntity duorouKgbotcamFile = duorouDetecedFileFormParam.getDuorouKgbotcamFile();
		return iotDataKgbotcamFileService.uploadDetectedFile(duorouDetecedFileFormParam.getFile(),duorouKgbotcamFile.getId());
	}



	/**
	 * 获取 待检测的多肉文件
	 * @param bucket 桶名称
	 * @param fileName 文件空间/名称
	 * @param response
	 * @return
	 */
	@Inner(false)
	@SneakyThrows
	@GetMapping("/{bucket}/{relativDir}/{year}/{month}/{day}/{fileName}")
	public void getToDetFile(@PathVariable String bucket,
							 @PathVariable String relativDir,
							 @PathVariable String year,
							 @PathVariable String month,
							 @PathVariable String day,
							 @PathVariable String fileName,
							 HttpServletResponse response) {
		String fileDir=String.format("%s/%s/%s/%s/%s",bucket, relativDir,year, month, day);
		iotDataKgbotcamFileService.getFile(fileDir, fileName, response);
	}

	/**
	 * 获取检测过后的多肉图片文件
	 * @param bucket 桶名称
	 * @param fileName 文件空间/名称
	 * @param response
	 * @return
	 */
	@Inner(false)
	@SneakyThrows
	@GetMapping("/{bucket}/{relativDir}/{year}/{month}/{day}/{detectedDir}/{fileName}")
	public void getDetectedFile(@PathVariable String bucket,
								@PathVariable String relativDir,
								@PathVariable String year,
								@PathVariable String month,
								@PathVariable String day,
								@PathVariable String detectedDir,
								@PathVariable String fileName,
								HttpServletResponse response) {
		String fileDir=String.format("%s/%s/%s/%s/%s/%s",bucket, relativDir,year, month, day,detectedDir);
		iotDataKgbotcamFileService.getFile(fileDir, fileName, response);
	}

}